package com.songlanyun.modules.order.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.enums.GoodsConstant;
import com.songlanyun.common.enums.OrderConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.*;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.modules.applyareaagent.service.ApplyAreaAgentService;
import com.songlanyun.modules.config.entity.ProfitSharingEntity;
import com.songlanyun.modules.config.service.ProfitSharingService;
import com.songlanyun.modules.exception.MemberException;
import com.songlanyun.modules.exception.OrderException;
import com.songlanyun.modules.express.model.JiSuKDUtil;
import com.songlanyun.modules.express.model.KDInfo;
import com.songlanyun.modules.marketing.firstorder.entity.FirstOrderActivity;
import com.songlanyun.modules.marketing.firstorder.service.FirstOrderActivityService;
import com.songlanyun.modules.order.dao.OrderDao;
import com.songlanyun.modules.order.entity.ChildOrder;
import com.songlanyun.modules.order.entity.HouniaoOrder;
import com.songlanyun.modules.order.entity.Order;
import com.songlanyun.modules.order.entity.OrderReceipt;
import com.songlanyun.modules.order.model.dto.UpdateOrderGoodsPriceDTO;
import com.songlanyun.modules.order.model.dto.UpdateOrderReceiptDTO;
import com.songlanyun.modules.order.model.vo.OrderPageReq;
import com.songlanyun.modules.order.model.vo.OrderVO;
import com.songlanyun.modules.order.model.vo.UserOrderNumStatisticsVo;
import com.songlanyun.modules.order.model.vo.UserOrderSlimStatisticsVo;
import com.songlanyun.modules.order.service.ChildOrderService;
import com.songlanyun.modules.order.service.HouniaoOrderService;
import com.songlanyun.modules.order.service.OrderReceiptService;
import com.songlanyun.modules.order.service.OrderService;
import com.songlanyun.modules.payorder.entity.PayOrder;
import com.songlanyun.modules.payorder.service.PayOrderService;
import com.songlanyun.modules.ship.model.dto.BranchShipVO;
import com.songlanyun.modules.shop.model.vo.ShopSlimVO;
import com.songlanyun.modules.useraddress.entity.UserAddress;
import com.songlanyun.modules.useraddress.service.UserAddressService;
import com.songlanyun.modules.usergains.service.UserBillService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, Order> implements OrderService {


    @Autowired
    private ChildOrderService childOrderService;

    @Autowired
    private JiSuKDUtil jiSuKDUtil;

    @Autowired
    private FirstOrderActivityService firstOrderActivityService;

    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private UserAddressService userAddressService;

    @Autowired
    private OrderReceiptService orderReceiptService;

    @Autowired
    private ApplyAreaAgentService applyAreaAgentService;

    @Autowired
    private HouniaoApiUtil houniaoApiUtil;

    @Autowired
    private HouniaoOrderService houniaoOrderService;

    @Autowired
    private UserBillService userBillService;

    @Autowired
    private ProfitSharingService profitSharingService;

    /**
     * 创建订单内部调用
     *
     * @param entity
     * @return
     */
    @Override
    public Order create(Order entity) {
        ValidatorUtils.validateEntity(entity);
        this.baseMapper.insert(entity);
        return entity;
    }

    /**
     * 修改订单内部调用
     *
     * @param entity
     * @return
     */
    @Override
    public Order modify(Order entity) {
        this.baseMapper.updateById(entity);
        return entity;
    }

    @Override
    public void remove(Long id) {

    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<Order> page = this.page(
                new Query<Order>().getPage(params),
                new QueryWrapper<Order>()
        );

        return new PageUtils(page);
    }

    /**
     * 根据支付订单Id获取所有相关订单
     *
     * @param payOrderId
     * @return
     */
    @Override
    public List<Order> loadByPayOrderId(Long payOrderId) {
        List<Order> list = this.list(new LambdaQueryWrapper<Order>()
                .eq(Order::getPayOrderId, payOrderId));
        return list;
    }

    @Override
    public Order loadByShopIdAndId(Long shopId, Long orderId, boolean tw) {
        Order order = this.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getShopId, shopId)
                .eq(Order::getId, orderId)
                .last("limit 1")
        );
        if (order == null && tw) {
            throw new RRException(OrderException.ORDER_NOT_EXISTS);
        }

        return order;
    }

    @Override
    public Order loadById(Long orderId, boolean tw) {
        Order order = this.getById(orderId);
        if (order == null && tw) {
            throw new RRException(OrderException.ORDER_NOT_EXISTS);
        }
        return order;
    }

    @Override
    public Order loadByShopIdAndOrderNo(Long shopId, String orderNo, boolean tw) {
        Order order = this.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getShopId, shopId)
                .eq(Order::getOrderCode, orderNo)
                .last("limit 1")
        );
        if (order == null && tw) {
            throw new RRException(OrderException.ORDER_NOT_EXISTS);
        }

        return order;
    }

    @Override
    public Order loadByOrderNo(String orderNo,boolean tw) {
        Order order = this.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderCode, orderNo)
                .last("limit 1")
        );
        if (order == null && tw) {
            throw new RRException(OrderException.ORDER_NOT_EXISTS);
        }

        return order;
    }

    @Override
    public Order loadByUserIdAndId(Long userId, Long orderId, boolean tw) {
        Order order = this.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getId, orderId)
                .last("limit 1")
        );
        if (order == null && tw) {
            throw new RRException(OrderException.ORDER_NOT_EXISTS);
        }

        return order;
    }

    @Override
    public PageUtils userOrdersPage(Long userId, Map<String, Object> params) {
        OrderPageReq orderPageReq = paramsMapToReq(params);
        orderPageReq.setUserId(userId);
        IPage<Order> orderPage = this.baseMapper.userOrdersPage(new Query<Order>().getPage(params), orderPageReq);
        orderPage.getRecords().forEach(o -> {
            o.getChildOrderList(true);
            o.loadShop();
        });
        return new PageUtils(orderPage);

    }





    @Override
    public PageUtils shopOrderPage(Map<String, Object> params) {
        IPage<Order> orderPage = null;
        orderPage = this.baseMapper.shopOrdersPage(new Query<Order>().getPage(params), paramsMapToReq(params));
        orderPage.getRecords().forEach(
                o -> {
                    o.getChildOrderList(true);
                    o.loadOperator(MapUtil.getLong(params, "shop_id"));
                    o.loadOrderReceipt();
                    o.loadOrderSelfTake();
                    o.loadGroupBuyTeam();
                }
        );

        return new PageUtils(orderPage);
    }

    @Override
    public PageUtils areaOrdersPage(Map<String, Object> params) {
        Long areaAgentId = MapUtil.getLong(params, "area_agent_id");
        List<ShopSlimVO> shopSlimVOS = applyAreaAgentService.myOnlineShops(areaAgentId);
        List<Long> shopIds = shopSlimVOS.stream().map(ShopSlimVO::getId).collect(Collectors.toList());
        shopIds.add(0L);
        params.put("shopIds",shopIds);
        IPage<Order> orderPage = this.baseMapper.areaOrdersPage(new Query<Order>().getPage(params), paramsMapToReq(params));
        orderPage.getRecords().forEach(
                o -> {
                    o.getChildOrderList(true);
                    o.loadOperator(MapUtil.getLong(params, "shop_id"));
                    o.loadOrderReceipt();
                    o.loadOrderSelfTake();
                    o.loadGroupBuyTeam();
                }
        );

        return new PageUtils(orderPage);
    }



    @Override
    public PageUtils shopServiceOrderPage(Map<String, Object> params) {
        IPage<Order> orderPage = this.baseMapper.shopServiceOrderPage(new Query<Order>().getPage(params), paramsMapToReq(params));
        orderPage.getRecords().forEach(
                o -> {
                    o.getChildOrderList(true).forEach(ChildOrder::loadServiceCard);
                    o.loadServiceOrderContacts();
                }
        );
        return new PageUtils(orderPage);
    }

    /**
     * 用户收货地址
     * @param userId
     * @param dto
     */
    @Override
    public void userOrderReceipt(Long userId, UpdateOrderReceiptDTO dto) {
        Order order = this.loadByUserIdAndId(userId, dto.getReceiptId(), true);
        if(!OrderConstant.ShipStatus.NO_SHIP.equals(order.getShipStatus()))
        {
            throw new RRException(OrderException.SHIP_NOT_UPDATE_EXPRESS);
        }

        if(!OrderConstant.ShipmentMode.EXPRESS.equals(order.getShipmentMode()))
        {
            throw new RRException(OrderException.EXPRESS_NOT);
        }

        UserAddress userAddress = userAddressService.getByUserIdAndId(userId, dto.getReceiptId());
        if(userAddress==null)
        {
            throw new RRException(MemberException.USER_ADDRESS_NOT_EXISTS);
        }

        OrderReceipt orderReceipt = order.loadOrderReceipt();
        orderReceipt.setMobile(userAddress.getPhone());
        orderReceipt.setReceiver(userAddress.getName());
        orderReceipt.setLatitude(userAddress.getLatitude());
        orderReceipt.setLongitude(userAddress.getLongitude());
        orderReceipt.setAddress(userAddress.getAddress());
        orderReceipt.setAreaCode(userAddress.getAreaCode());
        orderReceipt.setAreaName(userAddress.getAreaName());
        orderReceipt.setCityCode(userAddress.getCityCode());
        orderReceipt.setCityName(userAddress.getCityName());
        orderReceipt.setProvinceCode(userAddress.getProvinceCode());
        orderReceipt.setProvinceName(userAddress.getProvinceName());
        orderReceiptService.modify(orderReceipt);
    }

    @Override
    public UserOrderNumStatisticsVo loadGeneralOrderStatistics(long userId) {
        UserOrderNumStatisticsVo userOrderNumStatisticsVo = new UserOrderNumStatisticsVo();
        Integer waitPayNum = payOrderService.waitPayNum(userId, OrderConstant.OrderType.SALE_ORDER,0);
        userOrderNumStatisticsVo.setWaitPayNum(waitPayNum);
        Integer[] areaFeatures = new Integer[]{0,1,2};
        int waitShipNum = this.count(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getTransactionStatus, OrderConstant.TransactionStatus.WAIT_SHIP)
                .eq(Order::getPaymentStatus, OrderConstant.PaymentStatus.SUCCESS)
                .in(Order::getAreaFeature, Arrays.asList(areaFeatures))
                .eq(Order::getOrderType, OrderConstant.OrderType.SALE_ORDER)
                .eq(Order::getAdminOrder, false));


        userOrderNumStatisticsVo.setWaitShipNum(waitShipNum);


        int waitReceivingNum = this.count(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getShipStatus, OrderConstant.ShipStatus.ALREADY_SHIP)
                .eq(Order::getReceiptStatus, OrderConstant.ReceiptStatus.NO)
                .in(Order::getAreaFeature, Arrays.asList(areaFeatures))
                .eq(Order::getOrderType, OrderConstant.OrderType.SALE_ORDER));
        userOrderNumStatisticsVo.setWaitReceivingNum(waitReceivingNum);

        int waitCommentNum = this.count(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getReceiptStatus, OrderConstant.ShipStatus.ALREADY_SHIP)
                .eq(Order::getCommentStatus, OrderConstant.CommentStatus.NO)
                .in(Order::getAreaFeature, Arrays.asList(areaFeatures))
                .eq(Order::getOrderType, OrderConstant.OrderType.SALE_ORDER));
        userOrderNumStatisticsVo.setWaitCommentNum(waitCommentNum);

        return userOrderNumStatisticsVo;
    }

    @Override
    public UserOrderNumStatisticsVo loadServiceOrderStatistics(long userId) {
        UserOrderNumStatisticsVo userOrderNumStatisticsVo = new UserOrderNumStatisticsVo();
        Integer waitPayNum = payOrderService.waitPayNum(userId, OrderConstant.OrderType.SERVICE_ORDER,null);
        userOrderNumStatisticsVo.setWaitPayNum(waitPayNum);

        int waitUseNum = this.count(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .between(Order::getTransactionStatus,3,4)
                .eq(Order::getPaymentStatus, OrderConstant.PaymentStatus.SUCCESS)
                .eq(Order::getOrderType, OrderConstant.OrderType.SERVICE_ORDER));
        userOrderNumStatisticsVo.setWaitUseNum(waitUseNum);

        int waitCommentNum = this.count(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getReceiptStatus, OrderConstant.ShipStatus.ALREADY_SHIP)
                .eq(Order::getCommentStatus, OrderConstant.CommentStatus.NO)
                .eq(Order::getOrderType, OrderConstant.OrderType.SERVICE_ORDER));

        userOrderNumStatisticsVo.setWaitCommentNum(waitCommentNum);
        return userOrderNumStatisticsVo;
    }

    @Override
    public UserOrderNumStatisticsVo loadApplyOrderStatistics(long userId) {
        UserOrderNumStatisticsVo userOrderNumStatisticsVo = new UserOrderNumStatisticsVo();
        Integer waitPayNum = payOrderService.waitPayNum(userId, OrderConstant.OrderType.SALE_ORDER,3);
        userOrderNumStatisticsVo.setWaitPayNum(waitPayNum);
        int waitShipNum = this.count(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getTransactionStatus, OrderConstant.TransactionStatus.WAIT_SHIP)
                .eq(Order::getPaymentStatus, OrderConstant.PaymentStatus.SUCCESS)
                .eq(Order::getAreaFeature, 3)
                .eq(Order::getOrderType, OrderConstant.OrderType.SALE_ORDER));

        userOrderNumStatisticsVo.setWaitShipNum(waitShipNum);


        int waitReceivingNum = this.count(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getShipStatus, OrderConstant.ShipStatus.ALREADY_SHIP)
                .eq(Order::getReceiptStatus, OrderConstant.ReceiptStatus.NO)
                .eq(Order::getAreaFeature, 3)
                .eq(Order::getOrderType, OrderConstant.OrderType.SALE_ORDER));
        userOrderNumStatisticsVo.setWaitReceivingNum(waitReceivingNum);

        int waitCommentNum = this.count(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getReceiptStatus, OrderConstant.ShipStatus.ALREADY_SHIP)
                .eq(Order::getCommentStatus, OrderConstant.CommentStatus.NO)
                .eq(Order::getAreaFeature, 3)
                .eq(Order::getOrderType, OrderConstant.OrderType.SALE_ORDER));
        userOrderNumStatisticsVo.setWaitCommentNum(waitCommentNum);

        return userOrderNumStatisticsVo;

    }

    @Override
    public BigDecimal loadEquityStatistics(Long userId) {
        return this.baseMapper.loadEquityStatistics(userId);

    }

    @Override
    public BigDecimal loadPlatformMonthEquity() {
        Date now = new Date();
        long startTime = DateUtil.beginOfMonth(now).getTime();
        long endTime = DateUtil.endOfMonth(now).getTime();

        return  this.baseMapper.loadPlatformMonthEquity(startTime,endTime);

    }


//    public static void main(String[] args) {
//        Date now = new Date();
//        Date st = DateUtil.beginOfMonth(now);
//        Date end = DateUtil.endOfMonth(now);
//
//        System.out.println(DateUtil.format(st,"yyyy-MM-dd HH:mm:ss"));
//        System.out.println(DateUtil.format(end,"yyyy-MM-dd HH:mm:ss"));
//
//
//        System.out.println(st.getTime());
//        System.out.println(end.getTime());
//    }



    @Override
    public BigDecimal loadActivatingOrderCount(List<Long> userIds) {
        return this.baseMapper.loadActivatingOrderCount(userIds);
    }


    @Override
    public PageUtils allOrderPage(Map<String, Object> params) {

        IPage<Order> orderPage = this.baseMapper.shopOrdersPage(new Query<Order>().getPage(params), paramsMapToReq(params));
        orderPage.getRecords().forEach(
                o -> {
                    o.getChildOrderList(true);
                    o.loadOrderReceipt();
                    o.loadOrderSelfTake();
                    o.loadGroupBuyTeam();
                }

        );
        return new PageUtils(orderPage);
    }

    @Override
    public Order loadByShopKey(Long shopId, Long orderId) {
        return this.baseMapper.loadByShopKey(shopId, orderId);
    }

    @Override
    public Order loadByUserKey(Long userId, Long orderId) {
        return this.baseMapper.loadByUserKey(userId, orderId);
    }

    /**
     * 主单退款成功
     *
     * @param order
     * @return
     */
    @Override
    public Order refundOperate(Order order) {
        order.setRightsStatus(OrderConstant.RightsStatus.COMPLETE);
        order.setEnd(true);
        order.setTransactionStatus(OrderConstant.TransactionStatus.CLOSE);
        order.setCloseMode(OrderConstant.CloseMode.REFUND_SUCCESS);
        order.setCloseTime(System.currentTimeMillis());
        this.modify(order);

        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        for (ChildOrder childOrder : childOrderList) {
            childOrderService.refundOperate(childOrder);
        }

        return order;
    }

    @Override
    public List<Order> loadNeedAutoStockUp() {

        /**
         * 第一条件是自提订单
         * 第二条件是支付成功
         * 第三条件是未备货
         * 第四条件是没有维权
         * 第五条件是有自动备货时间
         * 第六条件是自动备货时间过期（小于等当前时间）
         */
        return this.list(new LambdaQueryWrapper<Order>()
                .eq(Order::getShipmentMode, OrderConstant.ShipmentMode.PICK_UP.getCode())
                .eq(Order::getPaymentStatus, OrderConstant.PaymentStatus.SUCCESS.getCode())
                .eq(Order::getShipStatus, OrderConstant.ShipStatus.NO_SHIP.getCode())
                .eq(Order::getRightsStatus, OrderConstant.RightsStatus.NO.getCode())
                .gt(Order::getAutoStockUpLastTime, 0)
                .le(Order::getAutoStockUpLastTime, System.currentTimeMillis())
        );
    }

    @Override
    public String queryExpressExpNo(String expNo, String mobile) {
        try {
            KDInfo kdInfo = jiSuKDUtil.getOrderTracesByJsonByMobile(expNo, mobile);
            if (ObjectUtil.isNull(kdInfo)) {
                return "";
            }
            return JSONObject.toJSONString(kdInfo);
        } catch (Exception e) {
            return "";
        }
    }

    @Override
    public Integer getCountCommonOrder(Long shopId, Long userId) {
        return this.baseMapper.selectCount(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getShopId, shopId)
                .eq(Order::getPaymentStatus, OrderConstant.PaymentStatus.SUCCESS.getCode())
                .eq(Order::getMarketingType, 0));
    }

    @Override
    public UserOrderSlimStatisticsVo loadUserOrderSlimStatistics(Long shopId, Long userId) {
        UserOrderSlimStatisticsVo vo = this.baseMapper.loadUserOrderSlimStatistics(shopId, userId);

        return vo;
    }


    @Transactional
    @Override
    public void updateGoodsPrice(Long shopId, UpdateOrderGoodsPriceDTO dto, Function<Object, Object> callBack) {

        Order order = this.loadByShopIdAndId(shopId, dto.getOrderId(), true);
        if (!OrderConstant.PaymentStatus.NO_PAY.equals(order.getPaymentStatus())) {
            throw new RRException("只有待支付的订单才可以改价");
        }


        List<ChildOrder> childOrderList = order.getChildOrderList(false);
        ChildOrder currentChild = null;
        for (ChildOrder childOrder : childOrderList) {
            if (childOrder.getId().equals(dto.getChildOrderId())) {
                currentChild = childOrder;
                break;
            }
        }

        if (currentChild == null) {
            //子订单不存在
            throw new RRException(OrderException.CHILD_ORDER_NOT_EXISTS);
        }

        BigDecimal originalRealPrice = currentChild.getRealPrice();
        currentChild.setRealPrice(dto.getResultPrice());
        currentChild.setTotalRealPrice(MathUtils.setScale(dto.getResultPrice().doubleValue() * currentChild.getNumber()));
        currentChild.setTotalReduced(MathUtils.multiply(MathUtils.subtract(currentChild.getSalePrice(), currentChild.getRealPrice()), new BigDecimal(currentChild.getNumber())));


        //订单商品的总价
        BigDecimal totalAmount = MathUtils.setScale(childOrderList.stream().mapToDouble(c -> c.getTotalRealPrice().doubleValue()).sum());
        //订单商品总优惠
        BigDecimal totalReduced = MathUtils.setScale(childOrderList.stream().mapToDouble(c -> c.getTotalReduced().doubleValue()).sum());

        BigDecimal firstOrderReduced = BigDecimal.ZERO;
        Integer orderNum = this.getCountCommonOrder(order.getShopId(), order.getUserId());
        //如果没有下过普通订单，可以做首单优惠
        if (orderNum == 0) {
            FirstOrderActivity firstActivity = firstOrderActivityService.getByShopId(order.getShopId(), false);
            if (firstActivity != null) {
                //如果满足首单优惠
                if (totalAmount.compareTo(firstActivity.getFull()) > 0) {
                    firstOrderReduced = firstActivity.getReduction();
                    //开始计算首单优惠分摊=======================================
                    if (childOrderList.size() == 1) {
                        childOrderList.get(0).setFirstOrderReduced(firstOrderReduced);
                    } else {
                        BigDecimal sum = BigDecimal.ZERO;
                        //计算首单优惠分摊
                        for (ChildOrder co : childOrderList) {
                            BigDecimal temp = MathUtils.setScaleDown(co.getTotalRealPrice().doubleValue() * firstOrderReduced.doubleValue() / totalAmount.doubleValue());
                            sum = MathUtils.add(temp, sum);
                            co.setFirstOrderReduced(temp);
                        }
                        //如果出现少分摊的情况，要补回给第一个子订单
                        if (firstOrderReduced.compareTo(sum) > 0) {
                            BigDecimal value = MathUtils.subtract(firstOrderReduced, sum);
                            childOrderList.get(0).setFirstOrderReduced(MathUtils.add(childOrderList.get(0).getFirstOrderReduced(), value));
                        }
                    }

                }
            }
        }

        order.setFirstOrderReduced(firstOrderReduced);
        order.setTotalReduced(MathUtils.add(totalReduced, firstOrderReduced));
        //订单商品总价
        order.setGoodsAmount(totalAmount);
        //订单总费用
        order.setTotalAmount(MathUtils.setScale(totalAmount.doubleValue() + order.getRealFreight().doubleValue() - firstOrderReduced.doubleValue()));

        this.modify(order);

        childOrderList.forEach(child -> {
            childOrderService.modify(child);
        });

        PayOrder payOrder = payOrderService.getById(order.getPayOrderId());
        List<Order> orders = payOrder.loadOrders();
        BigDecimal payAmount = MathUtils.setScale(orders.stream().mapToDouble(c -> c.getTotalAmount().doubleValue()).sum());
        BigDecimal payReduced = MathUtils.setScale(orders.stream().mapToDouble(c -> c.getTotalReduced().doubleValue()).sum());
        payOrder.setTotalAmount(payAmount);
        payOrder.setTotalReduced(payReduced);
        payOrderService.modify(payOrder);

        String remark = String.format("商家【%s】的订单[%s]中商品:%s,最终价格从%s改成了%s",
                order.getShopName(), order.getOrderCode(), currentChild.getGoodsTitle(), originalRealPrice.toString(), dto.getResultPrice());
        if (callBack != null) {
            callBack.apply(remark);
        }
    }

    @Override
    public List<OrderVO> exportList(Map<String, Object> params) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 处理分页参数
        long curPage = 1;
        long limit = 10;
        if(params.get(Constant.LIMIT) != null){
            limit = Long.parseLong((String)params.get(Constant.LIMIT));
            params.put(Constant.LIMIT, limit);
        }
        if(params.get(Constant.PAGE) != null){
            curPage = Long.parseLong((String)params.get(Constant.PAGE));
            params.put("offset", (curPage - 1) * limit);
        }

        OrderPageReq orderPageReq = paramsMapToReq(params);

        // 查询需要导出的数据列表
        List<OrderVO> orderList = this.baseMapper.exportList(orderPageReq);
        orderList.forEach(
                o -> {
                    o.getChildOrderList(true);
                }
        );

        // 返回查询到的数据列表
        return orderList;
    }

    @Override
    public List<BranchShipVO> exportWaitShip(Map<String, Object> params) {

        List<BranchShipVO> orderList = this.baseMapper.exportWaitShip(paramsMapToReq(params));
        orderList.forEach(
                o -> {
                    o.getChildOrderInfo(true);
                }

        );
        return orderList;
    }




    private OrderPageReq paramsMapToReq(Map<String, Object> params) {
        OrderPageReq orderPageReq = new OrderPageReq();
        try{orderPageReq.setShopId(MapUtil.getLong(params, "shop_id"));}catch (Exception ex){}
        try{orderPageReq.setShopIds((List<Long>)params.get("shopIds"));}catch (Exception ex){}
        try{orderPageReq.setShopName(MapUtil.getStr(params, "shop_name"));}catch (Exception ex){}
        try{orderPageReq.setUserId(MapUtil.getLong(params, "user_id"));}catch (Exception ex){}
        try{orderPageReq.setMarketingType(MapUtil.getInt(params, "marketing_type"));}catch (Exception ex){}
        try{orderPageReq.setOrderCode(MapUtil.getStr(params, "order_code"));}catch (Exception ex){}
        try{orderPageReq.setMobile(MapUtil.getStr(params, "mobile"));}catch (Exception ex){}
        try{orderPageReq.setOrderCreatorMobile(MapUtil.getStr(params, "order_creator_mobile"));}catch (Exception ex){}
        try{orderPageReq.setReceiver(MapUtil.getStr(params, "receiver"));}catch (Exception ex){}
        try{orderPageReq.setPayOrderCode(MapUtil.getStr(params, "pay_order_code"));}catch (Exception ex){}
        try{orderPageReq.setShipmentMode(MapUtil.getInt(params, "shipment_mode"));}catch (Exception ex){}
        try{orderPageReq.setTransactionStatus(MapUtil.getInt(params, "transaction_status"));}catch (Exception ex){}
        try{orderPageReq.setOrderType(MapUtil.getInt(params, "order_type"));}catch (Exception ex){}
        try{orderPageReq.setAreaFeature(MapUtil.getInt(params, "area_feature"));}catch (Exception ex){}
        try{orderPageReq.setClient(MapUtil.getStr(params, "client"));}catch (Exception ex){}
        try{orderPageReq.setThird(MapUtil.getInt(params, "third"));}catch (Exception ex){}
        try{orderPageReq.setPayMode(MapUtil.getInt(params, "pay_mode"));}catch (Exception ex){}
        try{orderPageReq.setStartTime(MapUtil.getDate(params,"startTime"));}catch (Exception ex){}
        try{orderPageReq.setEndTime(MapUtil.getDate(params,"endTime"));}catch (Exception ex){}
        try{orderPageReq.setOffset(MapUtil.getInt(params, "offset"));}catch (Exception ex){}
        try{orderPageReq.setLimit(MapUtil.getInt(params, "limit"));}catch (Exception ex){}
        try{orderPageReq.setWithClosed(MapUtil.getInt(params, "withClosed"));}catch (Exception ex){}

        return orderPageReq;

    }

    @Override
    public R houniaoTest() {
//        // 商品渲染（检查）
//        JSONObject checkGoods = new JSONObject();
//        checkGoods.put("area_id", 210102);
//        checkGoods.put("goods_spu", "GM00075028");
//        checkGoods.put("sku_id", "100032661");
//        checkGoods.put("goods_num", 1);
//
//        JSONObject checkGoodsRes = houniaoApiUtil.client(checkGoods, HouniaoConstant.CHECK_GOODS_ORDER.getUrl());
//        log.debug("商品渲染" + checkGoodsRes.toJSONString());
//
//        if (200 != checkGoodsRes.getInteger("code")) {
//            throw new RuntimeException("订单渲染失败");
//        }
//
//        // 获取运费
//        JSONObject getFreight = new JSONObject();
//        getFreight.put("area_id", 210102);
//        getFreight.put("sku_id", "100032661");
//        getFreight.put("goods_num", 1);
//
//        JSONObject getFreightRes = houniaoApiUtil.client(getFreight, HouniaoConstant.GET_FREIGHT.getUrl());
//        log.debug("获取运费" + getFreightRes.toJSONString());

        // 创建订单
        JSONObject buyNow = new JSONObject();

        buyNow.put("source_order_no", "houniao" + String.valueOf(Instant.now().getEpochSecond()));
        buyNow.put("username", "王义斐"); // 收件人姓名
        buyNow.put("user_phone", "13236932480");

//        buyNow.put("id_card", "");
//        buyNow.put("id_card_front_img", "");
//        buyNow.put("id_card_back_img", "");
//        buyNow.put("remark", "");
//        buyNow.put("is_pay", "");
//        buyNow.put("customs_platform_code", "");
//        buyNow.put("customs_platform_name", "");
//        buyNow.put("declarer", "");
//        buyNow.put("declarer_id_card", "");
//        buyNow.put("source_platform_no", "");
//        buyNow.put("amount_freight", "");
//        buyNow.put("amount_discount", "");
//        buyNow.put("amount_paid_in", "");
//        buyNow.put("pay_type", "");
//        buyNow.put("pay_no", "");
//        buyNow.put("pay_time", "");

//        buyNow.put("area_id", 210102);
//        buyNow.put("user_address", "市政府");
//        buyNow.put("create_time", Instant.now().getEpochSecond());
//
//        List<JSONObject> goods = new ArrayList<>();
//        JSONObject orderGoods = new JSONObject();
//        orderGoods.put("goods_spu", "GM00075028");
//        orderGoods.put("sku_id", "100032661");
//        orderGoods.put("goods_num", 1);
//        goods.add(orderGoods);
//
//        buyNow.put("order_goods", goods.toString());
//
//        JSONObject buyNowRes = houniaoApiUtil.client(buyNow, HouniaoConstant.ORDER_BUYNOW.getUrl());
//        log.debug("创建订单" + buyNowRes.toJSONString());
//
//        List<String> orderNos = new ArrayList<>();
//
//        JSONArray orderNoArr = buyNowRes.getJSONObject("data").getJSONArray("order_nos");
//        orderNoArr.forEach( item -> {
//            String s = (String) item;
//            orderNos.add(s);
//        });
//
//        log.debug("订单号列表" + JSONObject.toJSONString(orderNos));
//
//
//        // 查询余额
//        JSONObject userMoney = new JSONObject();
//        JSONObject userMoneyRes = houniaoApiUtil.client(userMoney, HouniaoConstant.USERS_MONEY.getUrl());
//        log.debug("查询余额" + userMoneyRes.toJSONString());

//        // 余额支付
//        orderNos.forEach( item -> {
//            String orderNo = (String) item;
//            JSONObject balancePay = new JSONObject();
//            balancePay.put("order_no", orderNo);
//
//            JSONObject balancePayRes = houniaoApiUtil.client(balancePay, HouniaoConstant.BALANCE_PAY.getUrl());
//            log.debug("余额支付" + balancePayRes.toJSONString());
//        });

        HouniaoOrder houniaoOrder = houniaoOrderService.getById(1);



        return R.ok().put("123", houniaoOrder);

    }

    @Override
    public BigDecimal getCountTotalAmount(LocalDate firstDayOfLastMonth, LocalDate lastDayOfLastMonth) {
        String start = firstDayOfLastMonth.toString()+" 00:00:00";
        String end = lastDayOfLastMonth.toString()+" 23:59:59";
        return this.baseMapper.getCountTotalAmount(start, end);
    }

    @Override
    public void writeOff(Long userId, String orderCode) {
        Order order = this.baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderCode, orderCode));
        if (order.getWriteOff()){
            throw new RRException("该订单已核销！");
        }
        if (userId.equals(order.getUserId())){
            throw new RRException("不能核销自己的订单！");
        }
        //订单核销配置表
        ProfitSharingEntity info = profitSharingService.info();
        BigDecimal consumerDirectPushReward = info.getConsumerDirectPushReward();


        //比例除以100
        BigDecimal divide = consumerDirectPushReward.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);

        //计算后的值
        BigDecimal scale = order.getTotalAmount().multiply(divide).setScale(2, RoundingMode.HALF_UP);

        //TODO 核销订单 做记录
        userBillService.writeOff(userId,scale,orderCode);

        //根据订单金额 按比例分配扣贡献值，给积分，做记录
        order.setWriteOff(true);
        this.baseMapper.updateById(order);
    }


}
